package m

import (
	"GameServer/Common/data"
	"GameServer/Common/utils"
	"GameServer/Game/cache"
	"GameServer/Game/dbmodule"
	"GameServer/Game/errors"
	"fmt"
	"sort"
	"sync"

	"github.com/globalsign/mgo/bson"
	log "github.com/sirupsen/logrus"
)

// 委托玩家
type ERGamer struct {
	BaseM
	Uid         bson.ObjectId `bson:"_id" json:"_uid"`
	Name        string        `bson:"name" json:"name"`               // 名字
	Head        string        `bson:"head" json:"head"`               // 头像
	AvatarFrame int64         `bson:"avatarFrame" json:"avatarFrame"` // 头像框
	Robot       bool          `bson:"robot" json:"robot"`             // true：机器人 false：是人

	RankId  int64 `bson:"rankId" json:"rankId"`   // 排名
	Honor   int64 `bson:"honor" json:"honor"`     // 累计荣誉
	GroupId int64 `bson:"groupId" json:"groupId"` // 组ID
}

// 委托排名小组
type ERGroup struct {
	BaseM
	Uid    int64            `bson:"_id" json:"_id"`
	MGamer map[string]int64 `bson:"mGamer" json:"mGamer"`
	LGamer []*ERGamer       `bson:"lGamer" json:"lGamer"`
	rw     sync.RWMutex
}

// 委托活动
type ERActiv struct {
	BaseM
	Uid       int64 `bson:"_id" json:"_id"`
	ActivId   int64 `bson:"activId" json:"activId"` // 活动id
	BeginTime int64 `bson:"beginTime" json:"beginTime"`
	EndTime   int64 `bson:"endTime" json:"endTime"`
	RankRewd  int64 `bson:"rankRewd" json:"rankRewd"` // 排名奖励
}

// 委托玩家：创建
func NewERGamer() cache.EntryI {
	return &ERGamer{}
}

// 委托玩家：保存信息
func (erg *ERGamer) Save() (err error) {
	err = dbmodule.MgoDB.GameDB.Upsert("ERGamer", bson.M{"_id": erg.Uid}, erg)
	if err != nil {
		return
	}
	return
}

// 委托玩家：加载
func (erg *ERGamer) Load(key interface{}) (err error) {
	switch key.(type) {
	case string:
		if key.(string) == "" {
			return errors.New("无效的key load, key empty")
		}
		erg.Uid = bson.ObjectIdHex(key.(string))
	case bson.ObjectId:
		erg.Uid = key.(bson.ObjectId)
	default:
		log.WithFields(log.Fields{
			"method": "ERGamer_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return erg.LoadData()
}

// 委托玩家：加载数据
func (erg *ERGamer) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("ERGamer", bson.M{"_id": erg.Uid}, nil, &erg)
	if err != nil {
		if err.Error() == "not found" {
			return nil
		}
		return err
	}
	return
}

// 委托玩家：更新数据
func (erg *ERGamer) Update(val *ERGamer) {
	Cache.Put("ERGamer", val.Uid.Hex(), val) //arG.GroupId.Hex()
	val.UpdateData()
}

// 委托玩家：删除分组
func (erg *ERGamer) Delete() (err error) {
	Cache.Remove("ERGamer", erg.Uid)
	return dbmodule.MgoDB.GameDB.Remove("ERGamer", bson.M{"_id": erg.Uid})
}

// 委托玩家：删除所有分组
func (erg *ERGamer) DeleteAll() (err error) {
	return dbmodule.MgoDB.GameDB.RemoveAll("ERGamer", nil)
}

func (u *User) GetERGamer() *ERGamer {
	v, _ := Cache.Get("ERGamer", u.Uid.Hex())
	return v.(*ERGamer)
}

// 委托排名小组：创建
func NewERGroup() cache.EntryI {
	return &ERGroup{
		LGamer: make([]*ERGamer, 0),
		MGamer: make(map[string]int64),
	}
}

// 委托排名小组：保存信息
func (erg *ERGroup) Save() (err error) {
	err = dbmodule.MgoDB.GameDB.Upsert("ERGroup", bson.M{"_id": erg.Uid}, erg)
	if err != nil {
		return
	}
	return
}

// 委托排名小组：加载
func (erg *ERGroup) Load(key interface{}) (err error) {
	switch key.(type) {
	case int64:
		erg.Uid = key.(int64)
	default:
		log.WithFields(log.Fields{
			"method": "ERGroup_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return erg.LoadData()
}

// 委托排名小组：加载数据
func (erg *ERGroup) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("ERGroup", bson.M{"_id": erg.Uid}, nil, &erg)
	if err != nil {
		if err.Error() == "not found" {
			return nil
		}
		return err
	}
	return
}

// 委托排名小组：更新数据
func (erg *ERGroup) Update(val *ERGroup) {
	Cache.Put("ERGroup", val.Uid, val) //arG.GroupId.Hex()
	val.UpdateData()
}

// 委托排名小组：删除分组
func DeleteERGroup(id int64) (err error) {
	Cache.Remove("ERGroup", id)
	return dbmodule.MgoDB.GameDB.Remove("ERGroup", bson.M{"_id": id})
}

// 委托排名小组：删除所有分组
func (erg *ERGroup) DeleteAll() (err error) {
	return dbmodule.MgoDB.GameDB.RemoveAll("ERGroup", nil)
}

func (erg *ERGroup) ReSort() {
	sort.Slice(erg.LGamer, func(i, j int) bool {
		return erg.LGamer[i].Honor > erg.LGamer[j].Honor
	})
	for idx, item := range erg.LGamer {
		item.RankId = int64(idx)
		erg.MGamer[item.Uid.Hex()] = int64(idx)
	}
}

// 修改荣誉
func (erg *ERGroup) CalcHonor(uid string, honor int64) {
	// 小组修改数据，加锁
	erg.rw.Lock()
	defer erg.rw.Unlock()
	// 索引玩家位置
	gamerIdx, ok := erg.MGamer[uid]
	if !ok {
		return
	}
	gamer := erg.LGamer[gamerIdx] // 获取玩家信息
	gamer.Honor += honor          // 累计玩家荣誉
	erg.UpdateRank(gamer)         // 小组重新更新排名

	erg.Update(erg)
	if !gamer.Robot { //机器人，不单独存入数据库
		gamer.Update(gamer)
	}
}

// 小组更新排名
func (erg *ERGroup) UpdateRank(gamer *ERGamer) {
	list := make([]*ERGamer, 0)
	// 获取玩家在数组中的索引
	val, _ := erg.MGamer[gamer.Uid.Hex()]
	// 删除更新的玩家
	list = append(erg.LGamer[:val], erg.LGamer[val+1:]...)

	flag := true
	erg.LGamer = make([]*ERGamer, 0)

	rankId := int64(0)
	// 重新排名
	for _, item := range list {
		if flag && gamer.Honor >= item.Honor {
			gamer.RankId = rankId
			erg.LGamer = append(erg.LGamer, gamer)
			erg.MGamer[gamer.Uid.Hex()] = rankId // 重置数组索引位置

			rankId++
			flag = false
		}

		item.RankId = rankId
		erg.LGamer = append(erg.LGamer, item)
		erg.MGamer[item.Uid.Hex()] = rankId // 重置数组索引位置
		rankId++
	}
}

// 获取小组的排名信息
func (erg *ERGroup) GetRank() (r []*ERGamer) {
	r = make([]*ERGamer, 0)
	// 获取排名，加读锁
	erg.rw.RLock()
	defer erg.rw.RUnlock()

	for _, item := range erg.LGamer {
		r = append(r, item)
	}
	return
}

func (u *User) GetERGroup() *ERGroup {
	gamer := u.GetERGamer()
	v, _ := Cache.Get("ERGroup", gamer.GroupId)
	return v.(*ERGroup)
}

func GetERGroup(id int64) *ERGroup {
	v, _ := Cache.Get("ERGroup", id)
	return v.(*ERGroup)
}

func NewERGamerRobot() *ERGamer {
	return &ERGamer{
		Uid:         bson.NewObjectId(),
		Name:        fmt.Sprintf("%s", utils.GenName()),
		Head:        fmt.Sprintf("%s", utils.GenDefaultHead()),
		AvatarFrame: data.AvatarFrameEnum.DefaultFrame,
		Robot:       true,
	}
}

// 委托活动：创建
func NewERActiv() cache.EntryI {
	return &ERActiv{}
}

// 委托活动：保存信息
func (era *ERActiv) Save() (err error) {
	err = dbmodule.MgoDB.GameDB.Upsert("ERActiv", bson.M{"_id": era.Uid}, era)
	if err != nil {
		return
	}
	return
}

// 委托活动：加载
func (era *ERActiv) Load(key interface{}) (err error) {
	switch key.(type) {
	case int64:
		era.Uid = key.(int64)
	default:
		log.WithFields(log.Fields{
			"method": "ERActiv_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return era.LoadData()
}

// 委托活动：加载数据
func (era *ERActiv) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("ERActiv", bson.M{"_id": era.Uid}, nil, &era)
	if err != nil {
		if err.Error() == "not found" {
			return nil
		}
		return err
	}
	return
}

// 委托活动：更新数据
func (era *ERActiv) Update(val *ERActiv) {
	Cache.Put("ERActiv", val.Uid, val) //arG.GroupId.Hex()
	val.UpdateData()
}

// 委托活动：删除
func (era *ERActiv) Delete() (err error) {
	Cache.Remove("ERActiv", era.Uid)
	return dbmodule.MgoDB.GameDB.Remove("ERActiv", bson.M{"_id": era.Uid})
}

// 委托活动：删除所有
func (era *ERActiv) DeleteAll() (err error) {
	return dbmodule.MgoDB.GameDB.RemoveAll("ERActiv", nil)
}

func GetERActiv(uid int64) *ERActiv {
	v, _ := Cache.Get("ERActiv", uid)
	return v.(*ERActiv)
}
